using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace Pixysoft.Security
{
    public class Random
    {
        private const string DEFAULT_CHARLIST = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
        private const string READ_CHARLIST = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
        private const string READ_SMALLCHARLIST = "23456789ABCEFGHJKLMNPQRSTWXYZabcdefghijkmnpqrstuvwxyz";

        private static Random instance;
        public static Random Instance
        {
            get
            {
                lock (typeof(Random))
                {
                    if (instance == null)
                        instance = new Random();
                    return instance;
                }
            }
        }


        public byte[] GetRandomBytes(int length)
        {
            if (length <= 0)
            {
                return new byte[0];
            }
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

            byte[] ret = new byte[length];

            rng.GetNonZeroBytes(ret);

            return ret;
        }

        public string GetRandomString(int length, string charList)
        {
            if (length <= 0 || charList == null || charList.Trim() == "")
            {
                return string.Empty;
            }
            int num = charList.Length;
            char[] ret = new char[length];
            byte[] rnd = GetRandomBytes(length);
            for (int i = 0; i < rnd.Length; i++)
            {
                ret[i] = charList[rnd[i] % num];
            }
            return new string(ret);
        }

        public string GetRandomString(int length)
        {
            return GetRandomString(length, READ_CHARLIST);
        }

        public string GetSmallRandomString(int length)
        {
            return GetRandomString(length, READ_SMALLCHARLIST);
        }

        public string GetRandomInt(int length)
        {
            System.Random random = new System.Random(GetRandomSeed());

            StringBuilder builder = new StringBuilder();

            for (int i = 0; i < length; i++)
            {
                builder.Append(random.Next(10).ToString());
            }

            return builder.ToString();
        }

        public static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetNonZeroBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }

        private void test()
        {
            List<int> list = new List<int>();

            for (int i = 0; i < 1000; i++)
            {
                int seed = GetRandomSeed();

                if (list.Contains(seed))
                    throw new Exception(seed.ToString());

                list.Add(seed);
            }
        }
    }
}
